<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

namespace App\Services\System\Admin;

use App\Constant\ApiErrorCode;
use App\Exceptions\AuthException;
use App\Model\Admin\SystemRoleModel;
use App\Services\BaseServices;
use App\Services\System\SystemMenusServices;
use EasySwoole\Component\Singleton;
use EasySwoole\FastCache\Cache;
use EasySwoole\ORM\DbManager;
use phpDocumentor\Reflection\Types\Collection;

/**
 * Description of SystemRoleServices
 *
 * @author zike
 */
class SystemRoleServices extends BaseServices {

    use Singleton;

    /**
     * 获取表单所需的权限名称列表
     * @param int $level
     * @return array
     */
    public function getRoleFormSelect(int $level)
    {
        $list = $this->getRoleArray(['level' => $level, 'status' => 1]);
        $options = [];
        foreach ($list as $id => $role) {
            $options[] = ['label' => $role['role_name'], 'value' => $id];
        }
        return $options;
    }

    /**
     * 身份管理列表
     * @param array $where
     * @return array
     */
    public function getRoleList(array $where, int $level, $page = 1, $limit = 10) {
	$model = SystemRoleModel::create()->where('level', $level);
	if ($where['status'] !== '')
	    $model->where('status', $where['status']);
	if ($where['role_name'] !== '') {
	    $like = '%' . $where['role_name'] . '%';
	    $model->where("(role_name like ?)", [$like]);
	}
	$model = $model->limit($limit * ($page - 1), $limit)->withTotalCount();
	$list = $model->all(null); // 列表数据
	$result = $model->lastQueryResult();
	$count = $result->getTotalCount(); // 总条数	
	/** @var SystemMenusServices $service */
	$service = SystemMenusServices::getInstance();
	foreach ($list as &$item) {
	    $item = $item->toArray();
	    $item['rules'] = implode(',', $service->getMenusNames($item['rules']));
	}
	return compact('list', 'count');
    }

    /**
     * 获取指定权限的菜单
     * @param array $rules
     * @param int $type
     * @param string $cachePrefix
     * @return array|mixed
     * @throws \throwable
     */
    public function getRolesByAuth(array $rules, int $type = 1) {
	if (empty($rules))
	    return [];
	return SystemMenusServices::getInstance()->getRoleAuths($this->getRoleIds($rules), $type);
    }

    /**
     * 获取菜单id
     * @param array $rules
     * @return array
     */
    public function getRoleIds(array $rules) {
//	$rules = SystemRoleModel::create()->where('status', 1)->where($rules)->column('rules');
	//invoke方式，让ORM查询结束后马上归还资源，可以提高资源的利用率
	$rules = DbManager::getInstance()->invoke(function ($client) use ($rules) {
	    return SystemRoleModel::invoke($client)->where('status', 1)->where('id', $rules, 'IN')->field(['id', 'rules'])->column('rules');
	});
	return $rules ? array_unique(explode(',', implode(',', $rules))) : [];
    }

    /**
     * 获取权限
     * @return mixed
     */
    public function getRoleRules(array $where = []) {
	$rules = DbManager::getInstance()->invoke(function ($client) use ($where) {
	    return SystemRoleModel::invoke($client)->where($where)->column('rules');
	});
	return $rules ?? [];
    }

    /**
     * 获取权限名称
     * @return mixed
     */
    public function getRoleArray(array $where = []) {
	$roles = DbManager::getInstance()->invoke(function ($client) use ($where) {
	    return SystemRoleModel::invoke($client)->where($where)->indexBy('id');
	});
	return $roles ?? [];
    }

    ####################################################################################################
    ####################################################################################################
    ####################################################################################################

    /**
     * 当前管理员权限缓存前缀
     */
    const ADMIN_RULES_LEVEL = 'Admin_rules_level_';

    /**
     * 后台验证权限
     * @param 
     */
    public function verifiAuth($adminInfo, $rule, $method) {
	$auth = $this->getRolesByAuthCache($adminInfo['roles'], 2);
	if ($rule == 'setting/admin/logout') {
	    return true;
	}
	//验证访问接口是否存在
	if (!in_array($rule, array_map(function ($item) {
			    return trim(strtolower(str_replace(' ', '', $item)));
			}, array_column($auth, 'api_url')))) {
	    throw new AuthException(ApiErrorCode::ERR_RULE);
	}
	//验证访问接口是否有权限
	if (empty(array_filter($auth, function ($item) use ($rule, $method) {
			    if (trim(strtolower($item['api_url'])) === $rule && $method === trim(strtolower($item['methods'])))
				return true;
			}))) {
	    throw new AuthException(ApiErrorCode::ERR_AUTH);
	}
	return true;
    }

    /**
     * 获取指定权限
     * @param array $rules
     * @param int $type
     * @param string $cachePrefix
     * @return array|mixed
     * @throws \throwable
     */
    public function getRolesByAuthCache(array $rules, int $type = 1, string $cachePrefix = self::ADMIN_RULES_LEVEL) {
	if (empty($rules))
	    return [];
	$authKey = $cachePrefix . '_' . $type . '_' . implode('_', $rules);
	$auths = Cache::getInstance()->get($authKey);
	if ($auths === null) {
	    $auths = SystemMenusServices::getInstance()->getRoleAuths($this->getRoleIds($rules), $type);
	    Cache::getInstance()->set($authKey, $auths, 3 * 60);
	}
	return $auths;
    }

}
